package com.example.demo.warn.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.example.demo.warn.config.WarnConfiguration;
import com.example.demo.warn.manager.WarnEquipManager;
import com.example.demo.warn.mapper.WarnMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 预警服务实现
 *
 * @author yuanz
 * @date 2024/06/06
 */
@Slf4j
@Component
public class WarnComponent {

    @Resource
    private WarnMapper warnMapper;

    @Resource
    private WarnConfiguration warnConfiguration;

    @Resource
    private WarnEquipManager warnEquipManager;

    /**
     * 特定区域方向同归属地顺序被采预警
     *
     * @param date 当前时间区间
     */
    public void warnBySpecialZoneAndFollowAndAttrCode(Date date) {
        // 配置参数
        String equips = warnConfiguration.equips;
        int batchNum = warnConfiguration.batchNum;
        String attrCode = warnConfiguration.attrCode;

        // 顺序点位信息
        String[] equipArr = equips.split(",");
        int baseSizePoint = 2;
        int pointLength = equipArr.length;
        if (pointLength >= baseSizePoint) {
            for (int i = 1; i < pointLength; i++) {
                String currentEquip = equipArr[i];
                String warnEquip = equipArr[i - 1];
                long[] timesArr = warnEquipManager.getTimes(currentEquip, warnEquip);
                // 使用SQL进行预警数据获取
                Map<String, Object> param = new HashMap<>(8);
                param.put("type", "1");
                param.put("attrCode", attrCode);
                param.put("batchNum", batchNum);
                param.put("currentEquip", currentEquip);
                param.put("currentTimeStart", dealTime(date, timesArr[0]));
                param.put("currentTimeEnd", dealTime(date, 0));
                // 预警参数
                param.put("warnEquip", warnEquip);
                param.put("warnTimeStart", dealTime(date, timesArr[2]));
                param.put("warnTimeEnd", dealTime(date, timesArr[1]));
                // 查询当前点位符合条件的IMSI数据
                List<Map<String, Object>> attrCodeAndImsiMapList = warnMapper.queryImsiByAttrCode(param);
                attrCodeAndImsiMapList.forEach(attrCodeAndImsiMap -> {
                    String attr = MapUtil.getStr(attrCodeAndImsiMap, "attrCode");
                    String imsiListObj = MapUtil.getStr(attrCodeAndImsiMap, "imsi");
                    List<String> imsiList = JSONUtil.toList(imsiListObj, String.class);
                    String imsiInStr = imsiList.stream().collect(Collectors.joining("','", "'", "'"));
                    param.put("attrCode", attr);
                    param.put("imsiInStr", imsiInStr);
                    param.put("warnTme", DateUtil.format(date, "yyyy-MM-dd HH:mm:ss"));
                    param.put("warnEquip", " -> " + currentEquip);
                    boolean isToWarn = warnMapper.verifyImsiByParam(param);
                    // 根据参数获取上一个点位符合条件的IMSI数据并入库warn_gsm
                    if (isToWarn) {
                        warnMapper.warnBySpecialZoneAndFollowAndAttrCode(param);
                        log.info("warnBySpecialZoneAndFollowAndAttrCode:{}", "Successfully!");
                    }
                });
            }
        }
    }

    /**
     * 特定区域方向IMSI连续三点位出现预警
     *
     * @param date 当前时间区间
     */
    public void warnBySpecialZoneAndFollowAndImsi(Date date) {
        // 配置参数
        String equips = warnConfiguration.equips;
        String imsiStr = warnConfiguration.imsiStr;
        // 顺序点位信息
        String[] equipArr = equips.split(",");
        // 不少于3个点位
        int baseSizePoint = 3;
        int pointLength = equipArr.length;
        if (pointLength >= baseSizePoint) {
            for (int i = 2; i < pointLength; i++) {
                String currentEquip = equipArr[i];
                String middleEquip = equipArr[i - 1];
                String warnEquip = equipArr[i - 2];
                String[] imsiArr = imsiStr.split(",");
                String imsiInStr = "'" + String.join("','", imsiArr) + "'";
                // 当前节点的数据信息
                Map<String, Object> param = new HashMap<>(8);
                param.put("type", "2");
                param.put("imsiInStr", imsiInStr);
                param.put("currentEquip", equipArr[i]);
                long[] timesArrA = warnEquipManager.getTimes(currentEquip, middleEquip);
                param.put("currentTimeStart", dealTime(date, timesArrA[0]));
                param.put("currentTimeEnd", dealTime(date, 0));
                // 中间节点的数据信息
                param.put("middleEquip", middleEquip);
                param.put("middleTimeStart", dealTime(date, timesArrA[2]));
                param.put("middleTimeEnd", dealTime(date, timesArrA[1]));
                long[] timesArrB = warnEquipManager.getTimes(currentEquip, warnEquip);
                // 预警节点的数据信息
                param.put("warnEquip", " -> " + middleEquip + " -> " + currentEquip);
                param.put("warnTme", DateUtil.format(date, "yyyy-MM-dd HH:mm:ss"));
                param.put("warnTimeStart", dealTime(date, timesArrB[2]));
                param.put("warnTimeEnd", dealTime(date, timesArrB[1]));
                // 预警数据入库
                warnMapper.warnBySpecialZoneAndFollowAndImsi(param);
            }
        }
    }

    /**
     * 特定区域同归属地再次被采预警
     *
     * @param date 当前时间区间
     */
    public void warnBySpecialZoneAndAttrCode(Date date) {
        // 配置参数
        String equips = warnConfiguration.equips;
        int batchNum = warnConfiguration.batchNum;
        String attrCode = warnConfiguration.attrCode;

        // 顺序点位信息
        String[] equipArr = equips.split(",");
        List<String> equipList = Arrays.asList(equipArr);
        int baseSizePoint = 2;
        int pointLength = equipList.size();
        if (pointLength >= baseSizePoint) {
            for (int i = 0; i < pointLength; i++) {
                String currentEquip = equipList.get(i);
                List<String> warnEquipList = new ArrayList<>(equipList);
                warnEquipList.remove(currentEquip);
                long windowTime = warnEquipManager.getWindowTime();
                String warnEquipInStr = warnEquipList.stream().collect(Collectors.joining("','", "'", "'"));
                // 使用SQL进行预警数据获取
                Map<String, Object> param = new HashMap<>(8);
                param.put("type", "3");
                param.put("attrCode", attrCode);
                param.put("batchNum", batchNum);
                param.put("currentEquip", currentEquip);
                param.put("currentTimeStart", dealTime(date, windowTime));
                param.put("currentTimeEnd", dealTime(date, 0));
                // 预警参数
                param.put("warnEquipInStr", warnEquipInStr);
                param.put("warnTimeStart", dealTime(date, windowTime - 1800000));
                param.put("warnTimeEnd", dealTime(date, windowTime));
                // 查询当前点位符合条件的IMSI数据
                List<Map<String, Object>> attrCodeAndImsiMapList = warnMapper.queryImsiByAttrCode(param);
                attrCodeAndImsiMapList.forEach(attrCodeAndImsiMap -> {
                    String attr = MapUtil.getStr(attrCodeAndImsiMap, "attrCode");
                    String imsiListObj = MapUtil.getStr(attrCodeAndImsiMap, "imsi");
                    List<String> imsiList = JSONUtil.toList(imsiListObj, String.class);
                    String imsiInStr = imsiList.stream().collect(Collectors.joining("','", "'", "'"));
                    param.put("attrCode", attr);
                    param.put("imsiInStr", imsiInStr);
                    param.put("warnEquip", " -> " + currentEquip);
                    param.put("warnTme", DateUtil.format(date, "yyyy-MM-dd HH:mm:ss"));
                    boolean isToWarn = warnMapper.verifyImsiByParam(param);
                    // 根据参数获取上一个点位符合条件的IMSI数据并入库warn_gsm
                    if (isToWarn) {
                        warnMapper.warnBySpecialZoneAndFollowAndAttrCode(param);
                        log.info("warnBySpecialZoneAndAttrCode:{}", "Successfully!");
                    }
                });
            }
        }


    }

    private String dealTime(Date date, long offset) {
        DateTime dateTime = DateUtil.offsetMillisecond(date, (int) offset);
        return DateUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss");
    }
}
